feat(abstract-utxo): add Pearl fixed-script wallet surface - #9360
Conversation
CI status: blocked only on npm package creationEverything substantive is green. The single real failure is
This is a prerequisite for any new package rather than something fixable in the diff: Confirmed both scopes are missing, not just the one CI reports: Raised VL-7329 (assigned to @andyfischer-bitgo, Velocity / BitGoJS Trusted publishing) to create both packages and configure GHA as trusted publisher — same request as VL-6005 for The alternative would be marking the package |
pranishnepal
left a comment
There was a problem hiding this comment.
1 package(s) not found on npm:
- @bitgo/sdk-coin-pearl (modules/sdk-coin-pearl)
CI's red and drafted - unsubscribing
OttoAllmendinger
left a comment
There was a problem hiding this comment.
lgtm but check CI errors
|
@claude review |
|
Claude finished @manojkumar138's task —— View job Pearl (Duplex) Implementation Review ✅Todo List:
Overall Assessment: APPROVED ✅This is a well-implemented, clean addition that follows BitGoJS patterns correctly. The implementation is minimal and focused, following the established LTC pattern while properly handling Pearl's unique wasm-only nature. ✅ StrengthsArchitecture & Design
Integration Quality
Test Coverage
Error Handling Enhancement
Dependency Management
🔍 Minor ObservationsDocumentation
CI Status
Package Structure
📋 Verification Checklist
🎯 RecommendationReady to merge once VL-7329 creates the npm packages. The implementation is solid, well-tested, and follows all BitGoJS conventions. No code changes needed. The architectural decision to keep Review completed for commit f341484 |
There was a problem hiding this comment.
Pull request overview
Adds Pearl (and testnet Pearl) as wasm-only, fixed-script UTXO coin implementations in @bitgo/abstract-utxo, provides an @bitgo/sdk-coin-pearl registration shim, and aligns @bitgo/wasm-utxo dependency versions across UTXO-related modules to avoid duplicate WASM installs.
Changes:
- Register
pearl/tpearlcoin names inabstract-utxo, add minimalPearl/Tpearlcoin classes, and export them from the module surface. - Add
sdk-coin-pearlpackage that re-exports the coin classes and provides aregister()helper for SDK registration. - Improve
sdk-coreerror messaging when a statics UTXO coin has no@bitgo/utxo-libnetwork (wasm-only coins), and add test coverage for the new behavior. - Bump
@bitgo/wasm-utxofrom^4.21.1to^4.27.0across affected packages and lockfile.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Locks @bitgo/wasm-utxo to 4.27.0. |
| tsconfig.packages.json | Adds modules/sdk-coin-pearl to TS project references. |
| modules/utxo-staking/package.json | Bumps @bitgo/wasm-utxo dependency. |
| modules/utxo-ord/package.json | Bumps @bitgo/wasm-utxo dependency. |
| modules/utxo-descriptors/package.json | Bumps @bitgo/wasm-utxo dependency. |
| modules/utxo-core/package.json | Bumps @bitgo/wasm-utxo dependency. |
| modules/utxo-bin/package.json | Bumps @bitgo/wasm-utxo dependency. |
| modules/sdk-core/test/unit/bitgo/utils/abstractUtxoCoinUtil.ts | Adds test for actionable error message for wasm-only coins. |
| modules/sdk-core/src/bitgo/utils/abstractUtxoCoinUtil.ts | Introduces getUtxolibNetwork() helper and throws actionable error when network is missing. |
| modules/sdk-coin-pearl/tsconfig.json | Adds CJS build config for new package. |
| modules/sdk-coin-pearl/tsconfig.esm.json | Adds ESM build config for new package. |
| modules/sdk-coin-pearl/src/index.ts | Re-exports Pearl/Tpearl and adds register() shim. |
| modules/sdk-coin-pearl/README.md | Documents usage and wasm-only/utxo-lib absence. |
| modules/sdk-coin-pearl/package.json | Defines new package metadata, build scripts, and exports map. |
| modules/sdk-coin-pearl/.prettierrc.yml | Adds Prettier config for the new package. |
| modules/sdk-coin-pearl/.prettierignore | Adds Prettier ignore entries for build artifacts. |
| modules/sdk-coin-pearl/.npmignore | Controls npm publish contents. |
| modules/sdk-coin-pearl/.mocharc.yml | Adds mocha config (even though tests are delegated elsewhere). |
| modules/sdk-coin-pearl/.gitignore | Ignores build output and local artifacts. |
| modules/sdk-coin-pearl/.eslintignore | Ignores build output and local artifacts for linting. |
| modules/abstract-utxo/test/unit/impl/pearl/unit/index.ts | Adds unit tests for Pearl behavior (taproot-only, chain support, no utxo-lib network). |
| modules/abstract-utxo/src/names.ts | Registers pearl / tpearl names and base-name mapping. |
| modules/abstract-utxo/src/index.ts | Exports Pearl implementation from module entrypoint. |
| modules/abstract-utxo/src/impl/pearl/pearl.ts | Adds Pearl coin class (wasm-only). |
| modules/abstract-utxo/src/impl/pearl/tpearl.ts | Adds Tpearl coin class. |
| modules/abstract-utxo/src/impl/pearl/index.ts | Barrel export for Pearl implementation. |
| modules/abstract-utxo/src/impl/index.ts | Exposes pearl impl namespace. |
| modules/abstract-utxo/package.json | Bumps @bitgo/wasm-utxo dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add the Pearl (Duplex) coin classes to abstract-utxo and the sdk-coin-pearl registration shim, following PR 1 which defined the coin in statics. Pearl is served entirely through @bitgo/wasm-utxo and has no @bitgo/utxo-lib network registration, so no utxo-lib changes are needed here. Taproot-only support needs no override. supportsAddressType already delegates to fixedScriptWallet.supportsScriptType, which reports only p2tr and p2trMusig2 for this coin, and supportsAddressChain inherits that. The new test pins the behaviour so a regression in either layer is caught. Bump @bitgo/wasm-utxo to ^4.27.0, the first release carrying pearl and tpearl in CoinName. All six utxo packages are bumped together rather than abstract-utxo alone: mixed ranges made yarn resolve two copies of the wasm binary, one hoisted and one nested. sdk-core's getUtxoCoinScriptTypes2Of3 and getUtxoCoinScriptTypesForWalletType resolve statics' utxolibName into a utxo-lib network, which does not exist for Pearl. They now fail with an actionable message pointing at wasm-utxo instead of a bare `TypeError: invalid network`. Resolving those two through wasm is left for the wallet-platform work, since sdk-core does not depend on wasm-utxo today. Pearl is deliberately left out of the shared utxoCoins test fixtures: that infrastructure maps coin names to utxo-lib networks, which Pearl does not have. Coverage lives in the dedicated impl/pearl suite instead. Recovery via RecoveryProvider.forCoin is also left unimplemented for Pearl - Blockchair has no Pearl support, and the existing default throws ApiNotImplementedError. TICKET: CECHO-1791 Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
f341484 to
64662cf
Compare
|
Addressed the review feedback in Copilot's comment — fixed, plus a pre-existing bugThe ask was to assert the new error behaviour for Doing it surfaced something separate: that entire describe block was calling sdk-core: 530 → 532 passing. abstract-utxo unchanged at 1552. Prettier and eslint clean. Claude's review — no changes neededVerdict was "Ready to merge... No code changes needed", and it independently endorsed keeping Blocker resolvedVL-7329 is done — both packages now exist:
Given the unblock, the revert of PR 1 (#9362) is no longer needed and has been closed. |
Wire the Pearl (Duplex) coin classes from @bitgo/sdk-coin-pearl into the
bitgo module so `bitgo.coin('pearl')` and `bitgo.coin('tpearl')` resolve.
Completes the BitGoJS onboarding started in #9347 (statics) and #9360
(abstract-utxo + sdk-coin-pearl).
Registers in both mechanisms: registerCoinConstructors for eager
registration and getCoinConstructor for the lazy lookup.
Pearl and Tpearl are imported directly from @bitgo/sdk-coin-pearl rather
than through the ./coins barrel. Routing them through the barrel makes
coinFactory observe a partially initialised module and leaves unrelated
constructors such as TethLikeCoin undefined at registration time. Several
other coins in this file are imported directly for the same reason. The
barrel still re-exports Pearl/Tpearl so `import { Pearl } from 'bitgo'`
keeps working like every other coin.
Regenerate the Dockerfile with `yarn update-dockerfile` so the new module
is copied and linked for bitgo-express. This is generated content and the
dockerfile-check CI job diffs it, so it must be committed rather than
hand-edited.
TICKET: CECHO-1792
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Summary
Adds the Pearl (Duplex) fixed-script wallet surface to
abstract-utxo, plus thesdk-coin-pearlregistration shim. Follows #9347, which defined the coin in statics.No
utxo-libchanges — Pearl is served entirely through@bitgo/wasm-utxo. Per @OttoAllmendinger: no descriptors, no ordinals, noutxo-core, noutxo-bin.PR 2 of 3.
coinFactory/bitgomodule wiring follows in PR 3 (CECHO-1792).Changes
abstract-utxo/src/names.tspearl/tpearlregistered;Pearladded togetBaseNameFromMainnetabstract-utxo/src/impl/pearl/Pearl/Tpearlclassesabstract-utxo/src/impl/index.ts,src/index.tssdk-coin-pearl/register()shimtsconfig.packages.jsonsdk-core/.../abstractUtxoCoinUtil.tspackage.json+yarn.lock@bitgo/wasm-utxo^4.21.1→^4.27.0The coin classes are ~15 lines each, mirroring
impl/ltc/.Taproot-only comes for free
The TDD sketched a
getSupportedScriptTypes()override. It isn't needed —AbstractUtxoCoin.supportsAddressType()already delegates to wasm:and wasm-utxo 4.27.0 reports only the taproot types for Pearl. Verified — abstract-utxo's
p2trspelling resolves correctly against wasm'sp2trLegacy:supportsAddressChain()inherits this, so chains 30/31/40/41 are supported and 0/1/10/11/20/21 are not. Both are pinned in the new test rather than left implicit, so a regression in either layer is caught.Why all six wasm-utxo bumps
Bumping
abstract-utxoalone left two ranges in play, and yarn resolved two copies of the wasm binary — 4.27.0 nested underabstract-utxo, 4.21.1 hoisted at the root. Aligning all six collapses it to a single hoisted 4.27.0. The lockfile diff is one entry.This is a dependency-hygiene change, not Pearl support being added to
utxo-core/utxo-bin— no code in those packages changed.sdk-core— deliberately not fully fixedgetUtxoCoinScriptTypes2Of3()andgetUtxoCoinScriptTypesForWalletType()resolve statics'utxolibNameinto a utxo-lib network:For Pearl that is
undefined, and the code then threw a bareTypeError: invalid network. It now throws:I stopped there rather than routing these through wasm, because
sdk-coredoes not depend on@bitgo/wasm-utxoand adding a WASM binary to a core package is an architectural decision with bundle-size consequences for every consumer — not mine to make in this PR. There are no in-repo callers; both functions are public API consumed by wallet-platform / bitgo-ui. @OttoAllmendinger this is the spot that matters for WP onboarding — happy to take whichever direction you prefer (wasm dep in sdk-core, a lookup table, or handling it WP-side).Test coverage
New
abstract-utxo/test/unit/impl/pearl/unit/index.ts(7 tests), following theimpl/btgconvention: instantiation, chain, full name, testnet inheritance, taproot-only script types, taproot-only address chains, and an explicit assertion that no utxo-lib network exists for Pearl — no other checked-in coin has that profile, so it can't be inferred from an existing coin.Pearl is deliberately not added to the shared
utxoCoinsfixtures. That infrastructure maps coin names to utxo-lib networks (getNetworkForCoinNamethrows for unknown coins, andgetUtxoCoins()sorts byutxolib.getNetworkList()position), so Pearl has nothing to point at. Adding it would have meant reworking test infra shared by 17 suites, 8 of which resolve a utxolib network. The dedicated suite covers what this PR actually adds.RecoveryProvider.forCoinis also left without a Pearl case — Blockchair has no Pearl support, and the existing fallthrough already throwsApiNotImplementedError, which is the correct outcome rather than a silent wrong provider.Verification
abstract-utxosdk-corestaticsutxo-coreutxo-binutxo-descriptorsutxo-ordutxo-stakingZero failures.
abstract-utxo,sdk-coin-pearl,sdk-core, and all five wasm dependents build clean. Prettier clean; eslint clean (0 errors). Verified end-to-end thatsdk-coin-pearlre-exports both classes andregisteris callable, and thatgetFullNameFromCoinNameyieldsPearl/Testnet Pearl.Related
coinFactory+bitgomodule wiringTICKET: CECHO-1791
🤖 Generated with Claude Code